{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Pandas 重置索引详解\n",
        "\n",
        "本教程详细介绍 Pandas 中 `.reset_index()` 方法的用法，包括单级索引重置、多级索引重置等操作。\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import pandas as pd\n",
        "import numpy as np\n",
        "\n",
        "# 创建示例数据集\n",
        "np.random.seed(42)\n",
        "data = {\n",
        "    'ID': [1001, 1002, 1003, 1004, 1005, 1006],\n",
        "    '姓名': ['张三', '李四', '王五', '赵六', '钱七', '孙八'],\n",
        "    '年龄': [25, 30, 35, 28, 32, 27],\n",
        "    '部门': ['技术', '销售', '技术', '人事', '销售', '技术'],\n",
        "    '工资': [8000, 12000, 15000, 6000, 11000, 9000],\n",
        "    '入职日期': pd.date_range('2020-01-01', periods=6, freq='ME')\n",
        "}\n",
        "\n",
        "df = pd.DataFrame(data)\n",
        "print(\"原始数据集：\")\n",
        "df\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## `.reset_index()` - 重置索引\n",
        "\n",
        "`.reset_index()` 方法用于将行索引转换为普通列，并创建新的默认整数索引。\n",
        "\n",
        "**语法：** `DataFrame.reset_index(level=None, drop=False, inplace=False, col_level=0, col_fill='')`\n",
        "\n",
        "**主要参数：**\n",
        "- `level`: 要重置的索引级别（用于多级索引），可以是整数、字符串或列表\n",
        "- `drop`: 布尔值，默认为 False，表示是否删除索引而不转换为列\n",
        "- `inplace`: 布尔值，默认为 False，表示是否在原 DataFrame 上修改\n",
        "- `col_level`: 如果列是多级索引，指定将索引插入到哪一级\n",
        "- `col_fill`: 重置多级索引时的列名填充值\n",
        "\n",
        "**适用场景：**\n",
        "- 将索引转换为普通列\n",
        "- 恢复默认的整数索引\n",
        "- 处理多级索引时，将某些级别转换为列\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 1.1 重置索引并转换为列（默认）\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 先设置索引\n",
        "df_reset1 = df.set_index('ID')\n",
        "\n",
        "print(\"=== 重置前的 DataFrame（ID 为索引）===\")\n",
        "print(df_reset1)\n",
        "\n",
        "# 重置索引（默认 drop=False，索引会变成列）\n",
        "df_reset2 = df_reset1.reset_index()\n",
        "print(\"\\n=== 重置索引后（drop=False，索引转为列）===\")\n",
        "df_reset2\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 1.2 重置索引并删除（drop=True）\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 重置索引并删除原索引（drop=True）\n",
        "df_reset3 = df_reset1.reset_index(drop=True)\n",
        "print(\"=== 重置索引后（drop=True，删除原索引）===\")\n",
        "df_reset3\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 1.3 重置多级索引\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 创建多级索引\n",
        "df_multi = df.set_index(['部门', '姓名'])\n",
        "\n",
        "print(\"=== 多级索引 DataFrame ===\")\n",
        "print(df_multi)\n",
        "print(\"\\n索引级别：\", df_multi.index.names)\n",
        "\n",
        "# 重置所有级别的索引\n",
        "df_multi_reset1 = df_multi.reset_index()\n",
        "print(\"\\n=== 重置所有级别的索引 ===\")\n",
        "df_multi_reset1\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 只重置指定级别的索引（level 参数）\n",
        "df_multi_reset2 = df_multi.reset_index(level='姓名')\n",
        "print(\"=== 只重置 '姓名' 级别的索引 ===\")\n",
        "df_multi_reset2\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 重置多个指定级别的索引\n",
        "df_multi_reset3 = df_multi.reset_index(level=[0, 1])  # 重置第一级和第二级\n",
        "print(\"=== 重置第一级和第二级索引 ===\")\n",
        "df_multi_reset3\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 1.4 使用 inplace 参数直接修改\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 创建副本用于演示\n",
        "df_reset4 = df.set_index('ID').copy()\n",
        "\n",
        "# 使用 inplace=True 直接修改\n",
        "df_reset4.reset_index(inplace=True)\n",
        "print(\"=== 使用 inplace=True 直接修改 ===\")\n",
        "df_reset4\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 综合应用示例\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 2.1 常见工作流程：设置索引 -> 数据操作 -> 重置索引\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 示例：按部门分组统计，使用部门作为索引更方便\n",
        "df_workflow = df.copy()\n",
        "\n",
        "# 步骤1：设置索引\n",
        "df_workflow = df_workflow.set_index('部门')\n",
        "\n",
        "# 步骤2：基于索引进行数据操作（例如：按部门筛选）\n",
        "tech_dept = df_workflow.loc['技术']\n",
        "print(\"=== 步骤1-2：设置索引并筛选技术部门 ===\")\n",
        "print(tech_dept)\n",
        "\n",
        "# 步骤3：重置索引以便进一步处理\n",
        "df_workflow = df_workflow.reset_index()\n",
        "print(\"\\n=== 步骤3：重置索引后 ===\")\n",
        "df_workflow\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 2.2 使用索引进行数据合并\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 创建两个数据集\n",
        "df_left = df[['ID', '姓名', '年龄']].set_index('ID')\n",
        "df_right = pd.DataFrame({\n",
        "    'ID': [1001, 1002, 1003, 1007],\n",
        "    '绩效': ['A', 'B', 'A', 'C']\n",
        "}).set_index('ID')\n",
        "\n",
        "print(\"=== 数据集1（左表）===\")\n",
        "print(df_left)\n",
        "print(\"\\n=== 数据集2（右表）===\")\n",
        "print(df_right)\n",
        "\n",
        "# 使用索引进行合并（更高效）\n",
        "df_merged = df_left.join(df_right, how='left')\n",
        "print(\"\\n=== 基于索引合并后的结果 ===\")\n",
        "df_merged\n",
        "\n",
        "# 合并后，如果需要重置索引\n",
        "df_merged_reset = df_merged.reset_index()\n",
        "print(\"\\n=== 重置索引后的结果 ===\")\n",
        "df_merged_reset\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 2.3 多级索引的分组操作\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 创建多级索引并分组统计\n",
        "df_grouped = df.set_index(['部门', '姓名'])\n",
        "\n",
        "# 按部门分组统计平均工资\n",
        "avg_salary = df_grouped.groupby(level='部门')['工资'].mean()\n",
        "print(\"=== 按部门统计平均工资（多级索引分组）===\")\n",
        "print(avg_salary)\n",
        "\n",
        "# 重置索引以便更好地展示结果\n",
        "avg_salary_df = avg_salary.reset_index()\n",
        "print(\"\\n=== 重置索引后的结果 ===\")\n",
        "avg_salary_df.columns = ['部门', '平均工资']\n",
        "avg_salary_df\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 注意事项和最佳实践\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 3.1 drop 参数的选择\n",
        "\n",
        "- **drop=False（默认）**：将索引转换为普通列，保留索引数据。适合需要保留原索引信息的场景\n",
        "- **drop=True**：直接删除索引，不转换为列。适合确定不需要原索引的场景\n",
        "\n",
        "**建议**：在大多数情况下，建议使用 `drop=False` 以保留数据完整性。只有在确定不需要索引数据时才使用 `drop=True`。\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 3.2 inplace 参数的使用\n",
        "\n",
        "- **inplace=False（默认）**：返回新对象，原对象不变。适合需要保留原数据的场景\n",
        "- **inplace=True**：直接修改原对象，不返回新对象。适合数据量大或确定不需要原数据的场景\n",
        "\n",
        "**建议**：在数据处理流水线中，根据实际情况选择。如果需要进行多步操作，建议使用 `inplace=False` 以便随时查看中间结果。\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 3.3 多级索引重置的注意事项\n",
        "\n",
        "1. **level 参数的使用**：可以指定要重置的索引级别，可以是：\n",
        "   - 整数：0 表示第一级，1 表示第二级，以此类推\n",
        "   - 字符串：索引级别的名称\n",
        "   - 列表：同时重置多个级别\n",
        "\n",
        "2. **保留部分索引**：通过 `level` 参数可以只重置指定的级别，保留其他级别作为索引\n",
        "\n",
        "3. **数据导出前重置**：在导出数据到 CSV 或 Excel 等格式前，重置索引可以获得更清晰的表格格式\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 3.4 性能优化建议\n",
        "\n",
        "1. **避免频繁重置**：如果需要多次切换索引，考虑使用临时副本而不是频繁重置\n",
        "2. **批量重置**：对于多级索引，如果需要重置所有级别，直接调用 `reset_index()` 而不指定 `level` 参数会更高效\n",
        "3. **数据导出优化**：在数据导出前统一重置索引，而不是在每次操作后都重置\n",
        "\n",
        "**示例：**\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# 示例：数据处理流程中，在最后统一重置索引\n",
        "df_processed = df.set_index('部门')\n",
        "\n",
        "# 进行各种数据处理操作...\n",
        "df_processed = df_processed[df_processed['工资'] > 7000]\n",
        "\n",
        "# 最后统一重置索引以便导出\n",
        "df_final = df_processed.reset_index()\n",
        "print(\"=== 处理完成后重置索引 ===\")\n",
        "df_final\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 总结\n",
        "\n",
        "**`.reset_index()` 方法的核心要点：**\n",
        "- 用于将行索引转换为普通列\n",
        "- 支持重置所有或指定级别的索引（`level` 参数）\n",
        "- 可以控制是否删除索引（`drop` 参数）\n",
        "- 可以直接修改原对象（`inplace=True`）\n",
        "\n",
        "**使用场景：**\n",
        "- 数据导出或展示前，重置索引以获得更好的格式\n",
        "- 分组统计后，重置索引以便更好地展示结果\n",
        "- 数据合并后，重置索引以恢复常规的表格结构\n",
        "- 多级索引处理时，将部分级别转换为列\n",
        "\n",
        "**与 `.set_index()` 配合使用：**\n",
        "- 在数据处理流程中，可以先设置索引进行高效操作\n",
        "- 完成操作后，使用 `reset_index()` 恢复常规格式\n",
        "- 这种组合使用可以大大提高数据处理效率\n",
        "\n",
        "掌握索引的重置是 Pandas 数据处理的重要技能，能够让你的数据分析工作更加灵活高效！\n"
      ]
    }
  ],
  "metadata": {
    "language_info": {
      "name": "python"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 2
}
